﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Xml;
using Wangzeran.CodeMaker.Core.Tag;
using System.Reflection;
using System.IO;
using Wangzeran.CodeMaker.Core.Template;
using Wangzeran.CodeMaker.Core.DB;
using Wangzeran.CodeMaker.Core.Files;

namespace Wangzeran.CodeMaker.Core.Config
{
    /// <summary>
    /// 插件节点
    /// </summary>
    public class PlugInsSectionHandler : IConfigurationSectionHandler
    {
        /// <summary>
        /// 标签节点
        /// </summary>
        private const string TAGNODE = "tag";
        /// <summary>
        /// 模板节点
        /// </summary>
        private const string TEMPLATENODE = "template";
        /// <summary>
        /// 数据库节点
        /// </summary>
        private const string DATABASENODE = "database";
        /// <summary>
        /// 输出文件节点
        /// </summary>
        private const string OUTPUTFILE = "outputfile";

        /// <summary>
        /// 插件文件夹
        /// </summary>
        protected const string PlugInsPath = @"";
        //protected const string PlugInsPath = @"PlugIns\";
        /// <summary>
        /// 插件节点
        /// </summary>
        protected const string PlugInsNode = "plugIns";
        /// <summary>
        /// 类型属性
        /// </summary>
        protected const string TypeAttribute = "type";
        /// <summary>
        /// 插件类库的扩展名
        /// </summary>
        protected const string PlugInExt = ".dll";
        /// <summary>
        /// 程序集名称 属性标签
        /// </summary>
        protected const string AssemblyAttribute = "assembly";
        /// <summary>
        /// 插件完全限定名 属性标签
        /// </summary>
        protected const string FactoryAttribute = "factory";

        #region IConfigurationSectionHandler 成员

        public object Create(object parent, object configContext, XmlNode section)
        {
            string assemblyName, typeName;
            Assembly assembly;

            foreach (XmlNode node in section.ChildNodes)
            {
                try
                {
                    assemblyName = node.Attributes[AssemblyAttribute].Value.Trim();
                    typeName = node.Attributes[FactoryAttribute].Value.Trim();
                    assembly = GetAssembly(assemblyName);
                    if (assembly == null)
                    {
                        continue;
                    }
                }
                catch
                {
                    continue;
                }

                if (node.Name == TAGNODE)
                {
                    ITag factory = (ITag)assembly.CreateInstance(typeName);
                    if (factory != null)
                    {
                        TagPlugIns.RegisterTag(factory);
                    }
                }
                else if (node.Name == TEMPLATENODE)
                {
                    ITemplate factory = (ITemplate)assembly.CreateInstance(typeName);
                    if (factory != null)
                    {
                        TemplatePlugIns.Templates.Add(factory.TemplateName, factory);
                    }
                }
                else if (node.Name == DATABASENODE)
                {
                    IDBPlugInSupport factory = (IDBPlugInSupport)assembly.CreateInstance(typeName);
                    if (factory != null)
                    {
                        DBPlugIns.RegisterDatabase(factory);
                    }
                }
                else if (node.Name == OUTPUTFILE)
                {
                    IFile factory = (IFile)assembly.CreateInstance(typeName);
                    if (factory != null)
                    {
                        FilePlugIns.Files.Add(factory.FileExt, factory);
                    }
                }
            }

            return null;
        }

        #endregion

        /// <summary>
        /// 获取程序集
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private Assembly GetAssembly(string assemblyName)
        {
            string file = GetPlugInPath(assemblyName);
            if (!File.Exists(file))
            {
                return null;
            }

            Assembly assembly = Assembly.LoadFile(file);
            return assembly;
        }

        /// <summary>
        /// 获取插件DLL的绝对路径
        /// </summary>
        /// <param name="assemblyName">程序集名称</param>
        /// <returns></returns>
        protected string GetPlugInPath(string assemblyName)
        {
            string path = Assembly.GetExecutingAssembly().Location;
            path = path.Remove(path.LastIndexOf(@"\") + 1);
            return path + PlugInsPath + assemblyName + PlugInExt;
        }
    }
}
